#include "thermometerwidget.h"
#include "thermometerwidget_p.h"

#include <QPainter>

#define CIRCLE_RADIUS 2

ThermometerWidget::ThermometerWidget(QWidget *parent)
    : QWidget(parent)
    , d_ptr(new ThermometerWidgetPrivate(this))
{
    this->setMinimumSize(70, 267);

    Q_D(ThermometerWidget);

    d->pAnimation = new QPropertyAnimation(this, "value");
    d->pAnimation->setDuration(500);
    d->pAnimation->setEasingCurve(QEasingCurve::InOutQuad);
}

double ThermometerWidget::getValue()
{
    Q_D(ThermometerWidget);
    return d->value;
}

double ThermometerWidget::getMinValue()
{
    Q_D(ThermometerWidget);
    return d->minValue;
}

double ThermometerWidget::getMaxValue()
{
    Q_D(ThermometerWidget);
    return d->maxValue;
}

void ThermometerWidget::setValueWithAnimation(double value)
{
    Q_D(ThermometerWidget);
    d->pAnimation->setStartValue(d->value);
    d->pAnimation->setEndValue(value);
    d->pAnimation->start();
}

void ThermometerWidget::setValue(double value)
{
    Q_D(ThermometerWidget);
    if (value > d->maxValue)
        d->value = d->maxValue;
    else if (value < d->minValue)
        d->value = d->minValue;
    else
        d->value = value;
    this->update();
    emit valueChange(d->value);
}

void ThermometerWidget::setValue(int value)
{
    Q_D(ThermometerWidget);
    if (value > d->maxValue)
        d->value = d->maxValue;
    else if (value < d->minValue)
        d->value = d->minValue;
    else
        d->value = value * 1.0;
    this->update();
    emit valueChange(d->value);
}

void ThermometerWidget::setMinValue(double minValue)
{
    Q_D(ThermometerWidget);
    d->minValue = minValue;
    this->update();
}

void ThermometerWidget::setMaxValue(double maxValue)
{
    Q_D(ThermometerWidget);
    d->maxValue = maxValue;
    this->update();
}

void ThermometerWidget::resizeEvent(QResizeEvent *)
{
    Q_D(ThermometerWidget);
    d->centerX = this->width() / 2;
    d->barHeight = this->height() - d->top - d->radius * 2;
}

void ThermometerWidget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    //启用反锯齿
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);

    //绘制水银柱背景
    drawBarBg(&painter);

    //绘制刻度尺
    drawRuler(&painter);

    //绘制当前水银柱
    drawBar(&painter);

    //绘制当前温度值
    drawValue(&painter);
}

void ThermometerWidget::drawBarBg(QPainter *painter)
{
    painter->save();
    painter->setPen(Qt::NoPen);
    painter->setBrush(QColor(180, 180, 180));

    Q_D(ThermometerWidget);

    //计算水银柱背景的矩形区域
    double barX = d->centerX - d->barWidth / 2;
    QRectF barRect(barX, d->top, d->barWidth, d->barHeight);

    //计算水银柱底部圆形背景的矩形区域
    double circleDiam = d->radius * 2;
    double circleX = d->centerX - d->radius;
    double circleY = this->height() - circleDiam - 2;
    d->circleRect = QRectF(circleX, circleY, circleDiam, circleDiam);

    //绘制路径
    QPainterPath path;
    path.addRect(barRect);
    path.addEllipse(d->circleRect);
    path.setFillRule(Qt::WindingFill);
    painter->drawPath(path);

    painter->restore();
}

void ThermometerWidget::drawRuler(QPainter *painter)
{
    painter->save();
    painter->setPen(QColor(30, 30, 30));

    Q_D(ThermometerWidget);

    //计算刻度尺的垂直度竖线并绘制
    double leftOffset = d->centerX - d->barWidth / 2 - 5;
    double rightOffset = d->centerX + d->barWidth / 2 + 5;
    double rulerHeight = d->barHeight - 2;
    QLineF leftLine(QPointF(leftOffset, d->top), QPointF(leftOffset, d->top + rulerHeight));
    QLineF rightLine(QPointF(rightOffset, d->top), QPointF(rightOffset, d->top + rulerHeight));
    painter->drawLine(leftLine);
    painter->drawLine(rightLine);

    //计算刻度尺水平刻度的位置并绘制
    int longStep = 10;                  //长线的步长
    int shortStep = 2;                  //短线的步长
    int longLineLen = 10;               //长线的长度
    int shortLineLen = 6;               //短线的长度
    double initLeftX = leftOffset;      //左边刻度线X起始点
    double initRightX = rightOffset;    //右边刻度线X起始点
    double initY = d->top;              //刻度线Y起始点

    //每一格移动多少像素
    double increment = rulerHeight / (d->maxValue - d->minValue);
    for (int i = d->maxValue; i >= d->minValue; i = i - shortStep)
    {
        if (i % longStep == 0)
        {
            QLineF longLineLeft(QPointF(initLeftX - longLineLen, initY), QPointF(initLeftX, initY));
            QLineF longLineRight(QPointF(initRightX, initY), QPointF(initRightX + longLineLen, initY));
            painter->drawLine(longLineLeft);
            painter->drawLine(longLineRight);

            QString strValue = QString::number(i);
            double fontHeight = painter->fontMetrics().height();
            QRectF leftTextRt(initLeftX - longLineLen - 40, initY - fontHeight / 2, 30, 20);
            QRectF rightTextRt(initRightX + longLineLen + 10, initY - fontHeight / 2, 30, 20);
            painter->drawText(leftTextRt, Qt::AlignRight, strValue);
            painter->drawText(rightTextRt, Qt::AlignLeft, strValue);
        }
        else
        {
            QLineF shortLineLeft(QPointF(initLeftX - shortLineLen, initY), QPointF(initLeftX, initY));
            QLineF shortLineRight(QPointF(initRightX, initY), QPointF(initRightX + shortLineLen, initY));
            painter->drawLine(shortLineLeft);
            painter->drawLine(shortLineRight);
        }
        initY += increment * shortStep;
    }

    painter->restore();
}

void ThermometerWidget::drawBar(QPainter *painter)
{
    painter->save();
    painter->setPen(Qt::NoPen);

    Q_D(ThermometerWidget);
    if (d->value > 37.2)
        painter->setBrush(QColor(255, 0, 0));
    else
        painter->setBrush(QColor(0, 255, 0));

    //计算水银柱背景的矩形区域
    int rulerHeight = d->barHeight - 2;
    double increment = rulerHeight / (d->maxValue - d->minValue);
    double barX = d->centerX - d->barWidth / 2;
    double barY = d->top + (d->maxValue - d->value) * increment;
    QRectF barRect(barX, barY, d->barWidth, d->value * increment + 2);

    //绘制路径
    QPainterPath path;
    path.addRect(barRect);
    path.addEllipse(d->circleRect);
    path.setFillRule(Qt::WindingFill);
    painter->drawPath(path);

    painter->restore();
}

void ThermometerWidget::drawValue(QPainter *painter)
{
    painter->save();

    Q_D(ThermometerWidget);
    QFont font;
    font.setPixelSize(d->circleRect.width() * 0.4);
    painter->setFont(font);
    painter->setPen(Qt::white);

    QString strValue = QString::number(d->value, 'f', 1);
    painter->drawText(d->circleRect, Qt::AlignCenter, strValue);

    painter->restore();
}
